/*
  ArtToSpr Artworks/Draw to Sprite convertor
  Copyright (c) 1998 Tony Houghton

  This source is distributed under the GPL. Please see the file
  "COPYING" for details.
*/

#include <stdio.h>
#include <stdlib.h>

#include "hourglass.h"

#include "err.h"
#include "CRstring.h"
#include "wimplib.h"

static char zak[252];
static char err_taskname[32] = "ArtToSpr";

bool err_is_task;

const char err_OutOfMem[] = "Not enough memory";

void err_set_taskname(const char *name, bool task)
{
  err_is_task = task;
  CRstrncpy(err_taskname, name, sizeof(err_taskname));
}

#ifndef NDEBUG
#define FORCE_POSTMORTEM ((exit)(( \
	fprintf(stderr, "Forcing postmortem\n"), \
	*(int * volatile) 0 = *(int * volatile) 4, 0)))
#endif

bool err_check(const _kernel_oserror *er)
{
  if (!er)
    return false;
  xhourglass_smash();
  if (err_is_task)
  {
    if (wimp_report_error((_kernel_oserror *) er,
    		Wimp_ReportError_OK|Wimp_ReportError_Cancel, err_taskname)
    	== Wimp_ReportError_Cancel)
    {
    #ifndef NDEBUG
      FORCE_POSTMORTEM;
    #else
      (exit)(0);
    #endif
    }
  }
  else
  {
    fputs(er->errmess, stderr);
    putc('\n', stderr);
  #ifndef NDEBUG
    FORCE_POSTMORTEM;
  #endif
  }
  return true;
}

void err_check_fatal(const _kernel_oserror *er)
{
  if (!er)
    return;
  xhourglass_smash();
  if (err_is_task)
  {
    wimp_report_error((_kernel_oserror *) er, Wimp_ReportError_Cancel,
    		err_taskname);
  }
  else
  {
    fputs(er->errmess, stderr);
    putc('\n', stderr);
  }
#ifndef NDEBUG
  FORCE_POSTMORTEM;
#else
  (exit)(0);
#endif
}

#ifndef NDEBUG
bool err_debug_check(const _kernel_oserror * er,
	const char *file, int line, bool fatal, bool report)
{
  static char errmess[252];
  if (!er)
    return false;
  if (fatal)
    fprintf(stderr, "Fatal ");
  CRstrcpy(errmess, er->errmess);
  fprintf(stderr, "Error code 0x%x at line %d of file %s:\n  %s\n",
  	er->errnum, line, file, errmess);
  xhourglass_smash();
  if (report && !err_is_task)
  {
    switch (fatal)
    {
      case false:
        if (wimp_report_error((_kernel_oserror *) er,
        	Wimp_ReportError_OK|Wimp_ReportError_Cancel, err_taskname)
        	== Wimp_ReportError_Cancel)
        {
        #ifndef NDEBUG
          FORCE_POSTMORTEM;
        #else
          (exit)(0);
        #endif
        }
        return true;
      case true:
        wimp_report_error((_kernel_oserror *) er, Wimp_ReportError_Cancel,
        		err_taskname);
      #ifndef NDEBUG
        FORCE_POSTMORTEM;
      #else
        (exit)(0);
      #endif
    }
  }
  else if (fatal)
  {
  #ifndef NDEBUG
    FORCE_POSTMORTEM;
  #else
    (exit)(0);
  #endif
  }
  return false;
}
#endif

void err_report(int num, const char *mess)
{
  static _kernel_oserror er;
  er.errnum = num;
  CRstrncpy(er.errmess, mess, sizeof(er.errmess));
  xhourglass_smash();
  if (err_is_task)
    wimp_report_error(&er, Wimp_ReportError_OK, err_taskname);
  else
  {
    fputs(mess, stderr);
    putc('\n', stderr);
  }
}

void err_complain(int num, const char *mess)
{
  static _kernel_oserror er;
  er.errnum = num;
  CRstrncpy(er.errmess, mess, sizeof(er.errmess));
  xhourglass_smash();
  if (err_is_task)
  {
    if (wimp_report_error(&er,
    		Wimp_ReportError_OK|Wimp_ReportError_Cancel, err_taskname)
    	== Wimp_ReportError_Cancel)
    {
    #ifndef NDEBUG
      FORCE_POSTMORTEM;
    #else
      (exit)(0);
    #endif
    }
  }
  else
  {
    fputs(mess, stderr);
    putc('\n', stderr);
  }
}

void err_complain_fatal(int num, const char *mess)
{
  _kernel_oserror er;
  er.errnum = num;
  CRstrncpy(er.errmess, mess, sizeof(er.errmess));
  xhourglass_smash();
  if (err_is_task)
    wimp_report_error(&er, Wimp_ReportError_Cancel, err_taskname);
  else
  {
    fputs(mess, stderr);
    putc('\n', stderr);
  }
#ifndef NDEBUG
  FORCE_POSTMORTEM;
#else
  (exit)(0);
#endif
}
